using System;
using System.Collections.Generic;
using System.Text;

namespace RF_Jammer_Base
{
    class SourceNode
    {
        const double MAX_ANGLE = 360;
        const double MAX_PHASE = 180;
        
        private int id;
        private double xCoordinate;
        private double yCoordinate;
        private double maxPower;
        private double frequency;
        private double dispersionAngle;

        private double outputAngle;
        private double outputPower;
        private double outputPhase;

        /* public constructor for a new source node */
        public SourceNode(int id, double xCoordinate, double yCoordinate, double maxPower, double frequency)
        {
            this.id = id;
            this.dispersionAngle = 1;
            this.frequency = frequency;
            this.xCoordinate = xCoordinate;
            this.yCoordinate = yCoordinate;
            this.maxPower = maxPower;
            SourceNode.writeOut("New " + this.ToString(), Jammer.NOTICE);
        }

        public Boolean CheckAim(double xCoord, double yCoord)
        {
            double m1 = 0;
            double b1 = 0;

            double m2 = 0;
            double b2 = 0;

            double y1 = 0;
            double y2 = 0;

            /* Determine the slope of our bounding lines */
            m1 = Math.Tan((this.OutputAngle + this.dispersionAngle / 2) * (Math.PI / 180));
            m2 = Math.Tan((this.OutputAngle - this.dispersionAngle / 2) * (Math.PI / 180));

            /* Determine the y-intercept of our bounding lines */
            b1 = this.yCoordinate - (this.xCoordinate * m1);
            b2 = this.yCoordinate - (this.xCoordinate * m2);

            /* Determine the bounding y-values at the x-coordinate of our target */
            y1 = (m1 * xCoord) + b1;
            y2 = (m2 * xCoord) + b2;

            /* Check if our taget is within the radiation pattern of our antenna */
            /* Quadrant I */
            if (this.OutputAngle >= 0 && this.OutputAngle < 90)
            {
                /* Check if target node is in Quadrant I as well */
                if ( xCoord < 0 || yCoord < 0 )
                {
                    return false;
                }

                if ( yCoord > y1 && yCoord < y2 )
                {
                    return false;
                }
            }
            /* Quadrant II & III */
            else if (this.OutputAngle >= 90 && this.OutputAngle < 270)
            {
                /* Check if target node is in Quadrant II or III as well */
                if ( xCoord > 0 )
                {
                    return false;
                }

                if ( yCoord > y2 && yCoord < y1 )
                {
                    return false;
                }
            }
            /* Quadrant IV */
            else if (this.OutputAngle >= 270 && this.OutputAngle < 360)
            {
                /* Check if target node is in Quadrant I as well */
                if (xCoord < 0 || yCoord < 0)
                {
                    return false;
                }

                if (yCoord > y1 && yCoord < y2)
                {
                    return false;
                }
            }
            else
            {
                /* Error condition - angle out of bounds */
                SourceNode.writeOut("angle out of bounds", Jammer.ERROR);
                return false;
            }
            return true;
        }

        /* customized to string method for the source node object */
        public override string ToString()
        {
            string str = "";
            str += string.Format("Source Node {0}, ", id); 
            str += string.Format("Location: {0:F},{1:F}, ", xCoordinate, yCoordinate);
            str += string.Format("Max Power: {0:F}, ", maxPower);
            str += string.Format("Power: {0:F}, ", outputPower);
            str += string.Format("Phase: {0:F}, ", outputPhase);
            str += string.Format("Direction: {0:F}", outputAngle);
            return str;
        }

        /* customized debug output method for the source node object */
        private static void writeOut(string str, int level)
        {
            str = string.Format("Source Node {0} - ", str);
            Jammer.DebugOut(str, level);
        }

        /* function to intialize node with random output parameters */
        public void InitRandom()
        {
            Random rand = new Random();
            outputPower = rand.NextDouble() * this.maxPower;
            outputAngle = rand.NextDouble() * MAX_ANGLE;
            outputPhase = rand.NextDouble() * MAX_PHASE;          
        }

        /* public getter and setter for id property of source node */
        public int ID
        {
            get
            {
                return id;
            }
            set
            {
                id = value;
            }
        }

        /* public getter and setter for x coordinate property of source node */
        public double XCoordinate
        {
            get
            {
                return xCoordinate;
            }
            set
            {
                xCoordinate = value;
            }
        }

        /* public getter and setter for max power property of source node */
        public double MaxPower
        {
            get
            {
                return maxPower;
            }
            set
            {
                maxPower = value;
            }
        }

        /* public getter and setter for y coordinate property of source node */
        public double YCoordinate
        {
            get
            {
                return yCoordinate;
            }
            set
            {
                yCoordinate = value;
            }
        }

        /* public getter and setter for output angle property of source node */
        public double OutputAngle
        {
            get
            {
                return outputAngle;
            }
            set
            {
                outputAngle = value;
            }
        }

        /* public getter and setter for output power property of source node */
        public double OutputPower
        {
            get
            {
                return outputPower;
            }
            set
            {
                outputPower = value;
            }
        }

        /* public getter and setter for output phase property of source node */
        public double OutputPhase
        {
            get
            {
                return outputPhase;
            }
            set
            {
                outputPhase = value;
            }
        }
    }
}
